package com.ywu.bpmn.form.service.service;

import com.ywu.boot.context.YwuContext;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.bpmn.form.service.data.YwuFormInstanceRepository;
import com.ywu.bpmn.form.service.data.YwuFormInterfaceRepository;
import com.ywu.bpmn.form.service.dto.*;
import com.ywu.bpmn.form.service.entity.YwuFormDefinitionEntity;
import com.ywu.bpmn.form.service.entity.YwuFormInstanceEntity;
import com.ywu.bpmn.form.service.entity.YwuFormInterfaceEntity;
import com.ywu.bpmn.form.service.entity.YwuFormInterfaceVersionEntity;
import com.ywu.common.entity.PageList;
import com.ywu.common.gson.GsonUtils;
import com.ywu.common.page.PageService;
import com.ywu.common.result.CommonResult;
import com.ywu.common.utils.TimerIdGenerateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName YwuFormInterfaceUiService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2025/4/21 11:58
 * @Version 1.0
 **/
@Service
@Slf4j
public class YwuFormInterfaceUiService {
    @Autowired
    private YwuFormInterfaceRepository repository;

    @Autowired
    private YwuFormInstanceRepository instanceRepository;

    /**
    * @Author GroundDemo
    * @Description 根据当前租户ID查询数据
    * @Date 12:32 2025/4/21
    * @Param [dto, isQueryJson]
    * @return com.ywu.bpmn.form.service.entity.YwuFormDefinitionEntity
    **/
    private YwuFormInterfaceEntity queryEntityByTenantId(YwuFormInterfaceDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        YwuFormInterfaceEntity search = new YwuFormInterfaceEntity();
        search.setId(dto.getId());
        search.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        YwuFormInterfaceEntity queryRes = repository.getEntity(search);
        if (Objects.isNull(queryRes)) {
            return null;
        } else {
            return queryRes;
        }
    }

    /**
    * @Author GroundDemo
    * @Description 创建表单外部接口
    * @Date 12:30 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> createInterface(YwuFormInterfaceDto dto) {
        // 校验编码是否存在
        YwuFormInterfaceEntity search = new YwuFormInterfaceEntity();
        search.setCode(dto.getCode());
        YwuFormInterfaceEntity queryRes = repository.getEntity(search);
        if (Objects.nonNull(queryRes)) {
            // 编码已存在
            return CommonResult.error().setErrorCode("form.interface.code.has.exist");
        }
        // 构建插入对象
        YwuFormInterfaceEntity insert = new YwuFormInterfaceEntity();
        BeanUtils.copyProperties(dto, insert);
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        insert.setId(TimerIdGenerateUtil.nextId());
        insert.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        insert.createInfo(currentContext.getYwuContextUser().getUserAccount());
        // 创建的初始状态为草稿
        insert.setStatus(YwuFormDefinitionEntity.DRAFT_STATUS);
        insert.setCurrentVersion(0);
        insert.setHasNotReleased(0);
        repository.insert(insert);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 修改外部接口
    * @Date 12:31 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> updateInterface(YwuFormInterfaceDto dto) {
        // 校验是否有操作权限（当前租户下是否存在）
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        YwuFormInterfaceEntity queryRes = queryEntityByTenantId(dto);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("id.is.not.exist");
        }
        // 如果当前数据是草稿，则直接修改当前数据即可
        if (queryRes.getStatus().equals(YwuFormInterfaceEntity.DRAFT_STATUS)) {
            YwuFormInterfaceEntity update = new YwuFormInterfaceEntity();
            BeanUtils.copyProperties(dto, update);
            update.setCurrentVersion(queryRes.getCurrentVersion());
            update.setHasNotReleased(queryRes.getHasNotReleased());
            update.updateInfo(currentContext.getYwuContextUser().getUserAccount());
            update.setStatus(queryRes.getStatus());
            repository.update(update);
        } else {
            // 如果当前版本是已发布的，则需要去version表中插入一条版本为0的草稿数据，并将当前数据的HasNotReleased状态置为1
            // 构建草稿版本数据
            YwuFormInterfaceVersionEntity insertVersion = new YwuFormInterfaceVersionEntity();
            BeanUtils.copyProperties(dto, insertVersion);
            insertVersion.setResourceId(queryRes.getId());
            insertVersion.setId(TimerIdGenerateUtil.nextId());
            insertVersion.setVersion(0);
            insertVersion.createInfo(currentContext.getYwuContextUser().getUserAccount());
            insertVersion.setFormId(queryRes.getFormId());
            insertVersion.setFormVersion(queryRes.getFormVersion());
            insertVersion.setCode(queryRes.getCode());
            insertVersion.setTenantId(currentContext.getYwuContextTenant().getTenantId());
            // 修改原始数据的状态
            queryRes.setHasNotReleased(1);
            queryRes.updateInfo(currentContext.getYwuContextUser().getUserAccount());
            repository.update(queryRes);
            // 采用先删除原始草稿版本的数据，再插入新的草稿数据
            YwuFormInterfaceVersionEntity deleteVersion = new YwuFormInterfaceVersionEntity();
            deleteVersion.setVersion(0);
            deleteVersion.setResourceId(queryRes.getId());
            repository.deleteVersionByVersion(deleteVersion);
            repository.insertVersion(insertVersion);
        }
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 删除接口
    * @Date 12:41 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> deleteInterface(YwuFormInterfaceDto dto) {
        // 校验是否有操作权限（当前租户下是否存在）
        YwuFormInterfaceEntity queryRes = queryEntityByTenantId(dto);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("id.is.not.exist");
        }
        // 删除当前数据
        YwuFormInterfaceEntity delete = new YwuFormInterfaceEntity();
        delete.setId(dto.getId());
        repository.delete(delete);
        // 删除历史版本数据
        YwuFormInterfaceVersionEntity deleteVersion = new YwuFormInterfaceVersionEntity();
        deleteVersion.setResourceId(queryRes.getId());
        repository.deleteVersionByVersion(deleteVersion);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 分页查询表单外部接口
    * @Date 12:45 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryPageList(YwuFormInterfaceDto dto) {
        // 构建分页
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        dto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        PageService.execPageStartAndEnd(dto.getPageInfo());
        // 查询所有数量
        int count = repository.queryCount(dto);
        if (count == 0) {
            log.debug("empty list");
            PageList<YwuFormDefinitionEntity> pageList = new PageList<>(dto.getPageInfo().getPageIndex(),
                    dto.getPageInfo().getPageSize(), count, new ArrayList<>());
            return CommonResult.success(pageList);
        }
        // 查询所有数据
        List<YwuFormInterfaceEntity> queryList = repository.queryPageList(dto);
        // 批量查询需要填充草稿版本的信息
        List<String> ids = queryList.stream().filter(res ->
                        res.getStatus().equals(YwuFormInterfaceEntity.ONLINE_STATUS) && res.getHasNotReleased() == 1)
                .map(YwuFormInterfaceEntity::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            // 批量查询草稿版本
            List<YwuFormInterfaceVersionEntity> draftVersionList = repository.queryDraftVersionList(ids);
            // 构建map，方便后续填充
            Map<String, YwuFormInterfaceVersionEntity> draftMap = draftVersionList.stream()
                    .collect(Collectors.toMap(YwuFormInterfaceVersionEntity::getResourceId,
                            res -> res, (v1, v2) -> v1));
            // 填充数据
            for (YwuFormInterfaceEntity definitionEntity : queryList) {
                if (draftMap.containsKey(definitionEntity.getId())) {
                    YwuFormInterfaceVersionEntity draftInfo = draftMap.get(definitionEntity.getId());
                    BeanUtils.copyProperties(draftInfo, definitionEntity, "id", "createBy", "createDate", "updateBy", "updateDate");
                    definitionEntity.setId(draftInfo.getResourceId());
                }
            }
        }
        PageList<YwuFormInterfaceEntity> pageList = new PageList<>(dto.getPageInfo().getPageIndex(),
                dto.getPageInfo().getPageSize(), count, queryList);
        return CommonResult.success(pageList);
    }

    /**
    * @Author GroundDemo
    * @Description 发布表单外部接口
    * @Date 12:49 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    @Transactional
    public CommonResult<Object> publishInterface(YwuFormInterfaceDto dto) {
        // 校验是否有操作权限（当前租户下是否存在）
        YwuFormInterfaceEntity queryRes = queryEntityByTenantId(dto);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("id.is.not.exist");
        }
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        // 如果当前状态时草稿，则需要将当前数据的状态改为已发布
        if (queryRes.getStatus().equals(YwuFormInterfaceEntity.DRAFT_STATUS)) {
            YwuFormInterfaceEntity update = new YwuFormInterfaceEntity();
            BeanUtils.copyProperties(queryRes, update);
            update.updateInfo(currentContext.getYwuContextUser().getUserAccount());
            update.setStatus(YwuFormInterfaceEntity.ONLINE_STATUS);
            update.setCurrentVersion(queryRes.getCurrentVersion() + 1);
            update.setHasNotReleased(0);
            repository.update(update);
            // 添加一条版本记录
            YwuFormInterfaceVersionEntity insertVersion = new YwuFormInterfaceVersionEntity();
            BeanUtils.copyProperties(queryRes, insertVersion);
            insertVersion.setId(TimerIdGenerateUtil.nextId());
            insertVersion.setResourceId(queryRes.getId());
            insertVersion.createInfo(currentContext.getYwuContextUser().getUserAccount());
            insertVersion.setVersion(queryRes.getCurrentVersion() + 1);
            repository.insertVersion(insertVersion);
        } else {
            // 当前状态为已发布，需要读取草稿版本的数据，将其数据填充到原始表中
            YwuFormInterfaceVersionEntity searchEntity = new YwuFormInterfaceVersionEntity();
            searchEntity.setResourceId(queryRes.getId());
            searchEntity.setVersion(0);
            YwuFormInterfaceVersionEntity versionEntity = repository.getVersionEntity(searchEntity);
            if (Objects.isNull(versionEntity)) {
                // 不存在草稿版本，无法发布
                return CommonResult.error().setErrorCode("draft.version.is.not.exist");
            }
            YwuFormInterfaceEntity newFormEntity = new YwuFormInterfaceEntity();
            BeanUtils.copyProperties(versionEntity, newFormEntity);
            newFormEntity.setId(queryRes.getId());
            newFormEntity.setHasNotReleased(0);
            newFormEntity.setStatus(YwuFormInterfaceEntity.ONLINE_STATUS);
            newFormEntity.updateInfo(currentContext.getYwuContextUser().getUserAccount());
            newFormEntity.setCurrentVersion(queryRes.getCurrentVersion() + 1);
            repository.update(newFormEntity);
            // 将原始那条草稿版本的数据的版本号改为最新的版本号
            versionEntity.setVersion(queryRes.getCurrentVersion() + 1);
            repository.updateVersionById(versionEntity);
        }
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 查询表单外部接口历史版本列表
    * @Date 12:53 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryInterfaceVersionList(YwuFormInterfaceDto dto) {
        // 校验是否有操作权限（当前租户下是否存在）
        YwuFormInterfaceEntity queryRes = queryEntityByTenantId(dto);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("id.is.not.exist");
        }
        // 根据resourceId查询所有历史版本
        YwuFormInterfaceVersionDto search = new YwuFormInterfaceVersionDto();
        search.setResourceId(dto.getId());
        List<YwuFormInterfaceVersionEntity> searchList = repository.queryVersionList(search);
        if (CollectionUtils.isEmpty(searchList)) {
            return CommonResult.success(searchList);
        }
        // 如果最后一个元素是 0 版本，则提到最前面
        if (searchList.get(searchList.size() - 1).getVersion() == 0) {
            YwuFormInterfaceVersionEntity draftVersionEntity = searchList.get(searchList.size() - 1);
            searchList.remove(searchList.size() - 1);
            List<YwuFormInterfaceVersionEntity> newList = new ArrayList<>();
            newList.add(draftVersionEntity);
            newList.addAll(searchList);
            searchList = newList;
        }
        return CommonResult.success(searchList);
    }

    /**
    * @Author GroundDemo
    * @Description 删除历史版本
    * @Date 12:55 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    @Transactional
    public CommonResult<Object> deleteVersion(YwuFormInterfaceVersionDto dto) {
        if (dto.getVersion() != 0) {
            return CommonResult.error().setErrorCode("version.can.not.delete");
        }
        // 校验是否有操作权限（当前租户下是否存在）
        YwuFormInterfaceDto searchDto = new YwuFormInterfaceDto();
        searchDto.setId(dto.getResourceId());
        YwuFormInterfaceEntity queryRes = queryEntityByTenantId(searchDto);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("resource.id.is.not.exist");
        }
        // 删除数据
        YwuFormInterfaceVersionEntity delete = new YwuFormInterfaceVersionEntity();
        delete.setVersion(dto.getVersion());
        delete.setResourceId(dto.getResourceId());
        repository.deleteVersionByVersion(delete);
        // 修改原始数据的hasNotReleased状态为0
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        queryRes.setHasNotReleased(0);
        queryRes.updateInfo(currentContext.getYwuContextUser().getUserAccount());
        repository.update(queryRes);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 回退版本
    * @Date 12:57 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    @Transactional
    public CommonResult<Object> backVersion(YwuFormInterfaceVersionDto dto) {
        // 校验是否有操作权限（当前租户下是否存在）
        YwuFormInterfaceDto searchDto = new YwuFormInterfaceDto();
        searchDto.setId(dto.getResourceId());
        YwuFormInterfaceEntity queryRes = queryEntityByTenantId(searchDto);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("resource.id.is.not.exist");
        }
        if (queryRes.getStatus().equals(YwuFormInterfaceEntity.DRAFT_STATUS)) {
            // 当前操作状态，无法回退
            return CommonResult.error().setErrorCode("draft.status.can.not.back");
        }
        // 查询待回退的历史版本数据
        YwuFormInterfaceVersionEntity search = new YwuFormInterfaceVersionEntity();
        search.setResourceId(dto.getResourceId());
        search.setVersion(dto.getVersion());
        YwuFormInterfaceVersionEntity versionEntity = repository.getVersionEntity(search);
        if (Objects.isNull(versionEntity)) {
            return CommonResult.error().setErrorCode("version.is.not.exist");
        }
        // 删除草稿版本的数据（如果有的话）
        YwuFormInterfaceVersionEntity deleteDraft = new YwuFormInterfaceVersionEntity();
        deleteDraft.setResourceId(dto.getResourceId());
        deleteDraft.setVersion(0);
        repository.deleteVersionByVersion(deleteDraft);
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        // 添加一条新的草稿数据，数据来源就是之前查询的历史版本的数据
        YwuFormInterfaceVersionEntity insert = new YwuFormInterfaceVersionEntity();
        BeanUtils.copyProperties(versionEntity, insert);
        insert.setVersion(0);
        insert.setId(TimerIdGenerateUtil.nextId());
        insert.createInfo(currentContext.getYwuContextUser().getUserAccount());
        repository.insertVersion(insert);
        // 修改原始表中数据hasNotReleased状态为1
        queryRes.setHasNotReleased(1);
        queryRes.updateInfo(currentContext.getYwuContextUser().getUserAccount());
        repository.update(queryRes);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 执行历史版本的外部接口
    * @Date 17:35 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> execFormHandlerByVersion(YwuFormInterfaceVersionDto dto) {
        // 校验是否有操作权限（当前租户下是否存在）
        YwuFormInterfaceDto searchDto = new YwuFormInterfaceDto();
        searchDto.setId(dto.getResourceId());
        YwuFormInterfaceEntity queryRes = queryEntityByTenantId(searchDto);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("resource.id.is.not.exist");
        }
        // 根据当前resourceId和version版本查询接口信息
        YwuFormInterfaceVersionEntity search = new YwuFormInterfaceVersionEntity();
        search.setResourceId(dto.getResourceId());
        if (Objects.isNull(dto.getVersion())) {
            // 没有传版本，则使用最新版本的外部接口
            dto.setVersion(queryRes.getCurrentVersion());
        }
        search.setVersion(dto.getVersion());
        YwuFormInterfaceVersionEntity versionEntity = repository.getVersionEntity(search);
        if (Objects.isNull(versionEntity)) {
            return CommonResult.error().setErrorCode("version.not.exist");
        }
        // 根据表单id，表单版本查询实例
        YwuFormInstanceDto searchInstance = new YwuFormInstanceDto();
        searchInstance.setFormId(versionEntity.getFormId());
        searchInstance.setFormVersion(versionEntity.getFormVersion());
        List<YwuFormInstanceEntity> res = instanceRepository.queryInstanceListByField(searchInstance, dto.getExecParam());
        if (CollectionUtils.isEmpty(res)) {
            return CommonResult.success(new ArrayList<>());
        }
        String requireJson = versionEntity.getFormResJson();
        List<String> requireFields = GsonUtils.deserializeList(requireJson, String.class);
        ArrayList<Map<String, Object>> returnList = new ArrayList<>();
        res.forEach(item -> {
            Map<String, Object> returnMap = new HashMap<>();
            // 先填充元数据
            returnMap.put("interfaceId", versionEntity.getResourceId());
            returnMap.put("interfaceVersion", versionEntity.getVersion());
            returnMap.put("formId", versionEntity.getFormId());
            returnMap.put("formVersion", versionEntity.getFormVersion());
            returnMap.put("instanceId", item.getId());
            // 填充json中的字段值
            String formInstanceJson = item.getFormInstanceJson();
            List<YwuFormInstanceJsonDto> ywuFormInstanceJsonDtoList = GsonUtils.deserializeList(formInstanceJson, YwuFormInstanceJsonDto.class);
            for (YwuFormInstanceJsonDto ywuFormInstanceJsonDto : ywuFormInstanceJsonDtoList) {
                if (requireFields.contains(ywuFormInstanceJsonDto.getCode())) {
                    returnMap.put(ywuFormInstanceJsonDto.getCode(), ywuFormInstanceJsonDto.getValue());
                }
            }
            returnList.add(returnMap);
        });
        // 遍历每一个节点，将需要查询返回的数据填充到map对象中
        return CommonResult.success(returnList);
    }

    /**
    * @Author GroundDemo
    * @Description 执行外部接口
    * @Date 17:35 2025/4/21
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> execInterfaceByCode(YwuFormInterfaceVersionDto dto) {
        // 根据编码查询数据
        YwuFormInterfaceEntity searchEntity = new YwuFormInterfaceEntity();
        searchEntity.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        searchEntity.setCode(dto.getCode());
        YwuFormInterfaceEntity queryRes = repository.getEntity(searchEntity);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setErrorCode("resource.code.is.not.exist");
        }
        YwuFormInstanceDto searchInstance = new YwuFormInstanceDto();
        searchInstance.setFormVersion(queryRes.getFormVersion());
        searchInstance.setFormId(queryRes.getFormId());
        List<YwuFormInstanceEntity> res = instanceRepository.queryInstanceListByField(searchInstance, dto.getExecParam());
        if (CollectionUtils.isEmpty(res)) {
            log.warn("execInterfaceByCode no instance");
            return CommonResult.success(new ArrayList<>());
        }
        String requireJson = queryRes.getFormResJson();
        List<String> requireFields = GsonUtils.deserializeList(requireJson, String.class);
        ArrayList<Map<String, Object>> returnList = new ArrayList<>();
        res.forEach(item -> {
            Map<String, Object> returnMap = new HashMap<>();
            // 先填充元数据
            returnMap.put("instanceId", item.getId());
            returnMap.put("interfaceId", queryRes.getId());
            returnMap.put("interfaceVersion", queryRes.getCurrentVersion());
            returnMap.put("formId", queryRes.getFormId());
            returnMap.put("formVersion", queryRes.getFormVersion());
            // 填充json中的字段值
            String formInstanceJson = item.getFormInstanceJson();
            List<YwuFormInstanceJsonDto> ywuFormInstanceJsonDtoList = GsonUtils.deserializeList(formInstanceJson, YwuFormInstanceJsonDto.class);
            for (YwuFormInstanceJsonDto ywuFormInstanceJsonDto : ywuFormInstanceJsonDtoList) {
                String code = ywuFormInstanceJsonDto.getCode();
                if (requireFields.contains(code)) {
                    returnMap.put(code, ywuFormInstanceJsonDto.getValue());
                }
            }
            returnList.add(returnMap);
        });
        // 遍历每一个节点，将需要查询返回的数据填充到map对象中
        return CommonResult.success(returnList);
    }
}
